/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.devs.benchmark.topology;

import java.util.List;
import org.devs.benchmark.Util;
import org.devs.benchmark.modeling.CoupledType;
import org.devs.benchmark.modeling.ModelType;

/**
 *
 * @author Alejandro Moreno
 */
public class Systolic extends Network {

    int width;
    int height;

    public Systolic(String name, int width, int height, Class message) throws Exception {

        super(name, message);

        if (width < 1 || height < 1) {
            throw new Exception("Parameters are incorrect");
        }

        this.width = width;
        this.height = height;
    }



    public Systolic(String name, int width, int height, Class message, int recursion) throws Exception {

        super(name, message, recursion);

        if (width < 1 || height < 1 || recursion <1) {
            throw new Exception("Parameters are incorrect");
        }
        
        this.width = width;
        this.height = height;
        

    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }



    public void buildModel(){

        super.setModel(this.createSystolicNetwork(this.name, this.width, this.height, super.message, super.recursion));
    }
    

    public void connectSystolicNodes(CoupledType coupled, int width) {

        if (coupled.getModels().size() > 0) {

            List<ModelType> models = coupled.getModels();

            for (int i = 0; i < 6; i++) {

                addConnectionToParent(coupled, 0, i, i);
                addConnectionFromParent(coupled, 0, i, i);

            }

            for (int i = 0; i < (models.size() - 1); i++) {

                int j = (i + 1);
                if (j % width != 0) {
                    addConnection(coupled, i, 2, j, 5);
                    addConnection(coupled, j, 5, i, 2);
                    System.out.println(i + " " + j);
                }
                int k = (i + width);
                if (k < models.size()) {
                    addConnection(coupled, i, 3, k, 0);
                    addConnection(coupled, k, 0, i, 3);
                    System.out.println(i + " " + k);

                    k++;
                    if (k % width != 0) {

                        addConnection(coupled, i, 4, k, 1);
                        addConnection(coupled, k, 1, i, 4);
                        System.out.println(i + " " + k);
                    }
                }

            }

        }


    }

    public ModelType createSystolicNetwork(String name, int width, int height, Class message, int recursion) {
        return createSystolic(name, width, height,message, "", recursion);
    }

   

    public ModelType createSystolic(String name, int width, int height, Class message, String id, int recursion) {

        CoupledType coupled = null;

        if (recursion > 0) {

            coupled = new CoupledType(name + "_Coupled_" + id, Util.createInports(6, message), Util.createOutports(6, message));

            ModelType mod = null;

            for (int j = 0; j < height; j++) {

                for (int i = 0; i < width; i++) {
                    mod = createSystolic(name, width, height, message, id + "_" + j + "_" + i, recursion - 1);
                    coupled.getModels().add(mod);
                }


            }

            connectSystolicNodes(coupled,width);

        } else {


            coupled = buildNode(name, 6, message, id);


        }

        return coupled;

    }

    
}
